﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.UI;
using KamLib;


namespace Ext.Net.UIS
{

    /// <summary>
    /// Является пространством имён для UIS-объектов. 
    /// Все FieldBox обязательно вкладывать в него. 
    /// Может содержать вложенные EntityBox.
    /// </summary>
    public class EntityBox : Container, ITermBox
    {

        #region Constructors

        public EntityBox() : base() { }
        public EntityBox(string name) : base() { Name = name; }
        public EntityBox(Term term) : base() { Term = term; }
        // ReSharper disable DoNotCallOverridableMethodsInConstructor
        public EntityBox(string name, params AbstractComponent[] items) : base() { Name = name; Items.AddRange(items); }
        public EntityBox(Term term, params AbstractComponent[] items) : base() { Term = term; Items.AddRange(items); }
        // ReSharper restore DoNotCallOverridableMethodsInConstructor

        protected virtual void Initialize() { }

        #endregion

        public new Context Context { get; set; }
        public TermNode ParentTermNode { get; set; }
        public TermNode TermNode { get; set; }
        public Term Term { get; set; }
        public string Name { get; set; }

        /// <summary>
        /// Обязательно указать для первого EntityBox в иерархии 
        /// </summary>
        public virtual bool IsRoot { get; set; }

        public override string ToString()
        {
            return Name.yes() ? "EntityBox " + TermNode.GetPathName() : base.ToString();
        }


        #region Store

        public string StoreID { get; set; }

        private ProxyCollection _Proxy;
        public ProxyCollection Proxy { get { return _Proxy ?? (_Proxy = new ProxyCollection()); } }

        public CRUDUrls ProxyAPI
        {
            get
            {
                var proxy = Proxy.Primary;
                if (proxy == null)
                {
                    var pproxy = new PageProxy();
                    _Proxy.Add(pproxy);
                    return pproxy.API;
                }
                var pproxy2 = proxy as PageProxy;
                return pproxy2 == null ? null : pproxy2.API;
            }
        }

        #endregion


        #region Controls

        protected override void OnBeforeClientInit(Observable sender)
        {
            base.OnBeforeClientInit(sender);
            if (!IsRoot) return;

            Context = new Context();
            CreateControls(new UisCreateControlArgs(Context));
            Bin.AddRange(Context.Stores);

            AddBeforeClientInitScript(TermNode.GetInitScript());
        }

        public void CreateControls(UisCreateControlArgs e)
        {
            if (Term == null && Name.no())
                throw new Exception("UIS.EntityBox: you must set properties Name or Term.");

            TermNode = this.UisGetTermNode();
            if (TermNode == null) return;

            TermNode.StoreID = StoreID;
            var store = TermNode.Store;
            if (TermNode.StoreIsNative)
            {
                if (_Proxy != null && TermNode.Store.Proxy.Count == 0)
                    store.Proxy.AddRange(_Proxy);
                Context.Stores.Add(store);
            }

            for (var i = 0; i < Controls.Count; ++i)
            {
                CreateItemControls(TermNode, Controls[i], ref i, e);
            }
        }

        public bool ControlsCreated { get; set; }

        private void CreateItemControls(TermNode parentNode, Control control, ref int index, UisCreateControlArgs e)
        {
            var box = control as ITermBox;
            if (box != null && !box.ControlsCreated)
            {
                box.Context = Context;
                box.ParentTermNode = parentNode;
                box.CreateControls(e);
                box.ControlsCreated = true;
            }

            if (control is EntityBox)
            {
                var container = control as EntityBox;
                if (container.IsRoot) return;
                // Если этот control является EntityBox, то скрыть его, оставив на его месте его Items
                //if (container == null) return;
                var parent = container.ParentComponent as AbstractContainer;
                if (parent == null) return;

                index += container.Items.Count;
                var i = parent.Items.IndexOf(container);
                if (i >= 0)
                    parent.Items.InsertRange(i + 1, container.Items);
                else
                    parent.Items.AddRange(container.Items);
                container.Items.Clear();
            }
            else
            {
                var parentNode2 = box != null ? box.TermNode : parentNode;
                // Иначе искать дальше
                var container = control as AbstractContainer;
                if (container != null)
                {
                    for (var i = 0; i < container.Items.Count; ++i)
                    {
                        CreateItemControls(parentNode2, container.Items[i], ref i, e);
                    }
                }
                else
                {
                    for (var i = 0; i < control.Controls.Count; ++i)
                    {
                        CreateItemControls(parentNode2, control.Controls[i], ref i, e);
                    }
                }
            }
        }

        #endregion


        #region Для уменьшения генерируемого javascript

        [DefaultValue(false)]
        public override bool Visible { get { return IsRoot; } set { } }
        protected override void OnClientInit(bool reinit)
        {
            if (IsRoot)
                base.OnClientInit(reinit);
        }

        #endregion

    }



    public class RootEntityBox : EntityBox
    {
        public RootEntityBox() : base() { }
        public RootEntityBox(string name) : base() { Name = name; }
        public RootEntityBox(Term term) : base() { Term = term; }
        // ReSharper disable DoNotCallOverridableMethodsInConstructor
        public RootEntityBox(string name, params AbstractComponent[] items) : base() { Name = name; Items.AddRange(items); }
        public RootEntityBox(Term term, params AbstractComponent[] items) : base() { Term = term; Items.AddRange(items); }
        // ReSharper restore DoNotCallOverridableMethodsInConstructor

        public override bool IsRoot { get { return true; } set { } }
    }

}
